#include "usart1.h"

static uint8_t RxData[USART_BUFFER_SIZE];
struct USART_Buffer USART1_RxBuf = {.Data = RxData};

void USART1_Init()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 初始化 PA9
    GPIO_InitTypeDef GPIO_InitStruct = {
        .GPIO_Pin = GPIO_Pin_9,
        .GPIO_Mode = GPIO_Mode_AF_PP,
        .GPIO_Speed = GPIO_Speed_50MHz,
    };
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    // 初始化 PA10
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 初始化 USART1
    USART_InitTypeDef USART_InitStruct = {
        .USART_BaudRate = 4800,                                      // 波特率设置：4800
        .USART_WordLength = USART_WordLength_8b,                     // 数据位数设置：8位
        .USART_StopBits = USART_StopBits_1,                          // 停止位设置：1位
        .USART_Parity = USART_Parity_No,                             // 是否奇偶校验：无
        .USART_HardwareFlowControl = USART_HardwareFlowControl_None, // 硬件流控制模式设置：没有使能
        .USART_Mode = USART_Mode_Rx | USART_Mode_Tx,                 // 接收与发送都使能
    };
    USART_Init(USART1, &USART_InitStruct);
    // 中断配置
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    NVIC_EnableIRQ(USART1_IRQn);
    NVIC_SetPriority(USART1_IRQn, 7);
    // USART1 使能
    USART_Cmd(USART1, ENABLE);
}

// USART1 中断
void USART1_IRQHandler(void)
{
    int Ch = -1;

    if ((USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET) &&
        (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET))
    {
        while (1)
        {
            Ch = -1;
            // USART_IT_RXNE 在读取完 DR 寄存器后会自动清除
            if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
            {
                Ch = (char)USART_ReceiveData(USART1);
            }
            if (Ch == -1)
            {
                break;
            }
            uint32_t NewEnd = (USART1_RxBuf.End + 1) % USART_BUFFER_SIZE;
            if (NewEnd != USART1_RxBuf.Head)
            {
                USART1_RxBuf.Data[USART1_RxBuf.End] = Ch;
                USART1_RxBuf.End = NewEnd;
            }
        }
    }
}
